#ifndef WEBSERVER_H
#define WEBSERVER_H

#include <unordered_map>
#include <fcntl.h>       // fcntl()
#include <unistd.h>      // close()
#include <assert.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "epoll.h"
#include "../log/log.h"
#include "../timer/heaptimer.h"
#include "../pool/sqlconnpool.h"
#include "../pool/threadpool.h"
#include "../pool/sqlconnRAII.h"
#include "../http/httpconn.h"

class WebServer
{
public:
    //WebSever的构造函数，其参数分别如下：
    WebServer(
        //端口号
        int port, 
        //触发模式
        int trigMode, 
        //超时时间
        int timeoutMS, 
        //是否开启linger
        bool OptLinger, 
        //数据库端口
        int sqlPort, 
        //数据库用户名
        const char* sqlUser, 
        //数据库密码
        const  char* sqlPwd, 
        //数据库名
        const char* dbName, 
        //数据库连接池数量
        int connPoolNum, 
        //线程池数量
        int threadNum,
        //是否开启日志
        bool openLog, 
        //日志等级
        int logLevel, 
        //日志队列大小
        int logQueSize
    );
    ~WebServer();
    //启动服务器的函数
    void Start();
private:  
    //初始化socket的函数
    bool InitSocket_();
    //初始化事件模式
    void InitEventMode_(int trigMode);
    //添加客户端新连接的函数
    void AddClient_(int fd, sockaddr_in addr);
    //处理监听事件的函数
    void DealListen_();
    //处理写事件
    void DealWrite_(HttpConn* client);
    //处理读事件
    void DealRead_(HttpConn* client);
    //发送错误信息的函数，参数是fd和错误信息
    void SendError_(int fd, const char* info);
    //延长客户端连接超时事件
    void ExtentTime_(HttpConn* client);
    //关闭客户端连接的函数
    void CloseConn_(HttpConn* client);
    //读事件回调函数
    void OnRead_(HttpConn* client);
    //写事件回调函数
    void OnWrite_(HttpConn* client);
    //处理客户端请求
    void OnProcess_(HttpConn* client);
    ////最大文件描述符数量
    static const int MAX_FD = 65536;
    //设置文件描述符为非阻塞模式
    static int SetFdNonblock(int fd);
    ////端口号
    int port_;
    //是否开启linger
    bool openLinger_;
    //超时时间
    int timeoutMS_;
    //是否关闭服务器
    bool isClose_;
    //监听文件描述符
    int listenFd_;
    //源文件目录
    char* srcDir_;
    //监听事件类型
    uint32_t listenEvent_;
    //连接事件类型
    uint32_t connEvent_;
    //定时器
    std::unique_ptr<HeapTimer> timer_;
    //线程池
    std::unique_ptr<ThreadPool> threadpool_;
    //epoll实例
    std::unique_ptr<Epoller> epoller_;
    //客户端连接
    std::unordered_map<int, HttpConn> users_;
};
#endif